package org.server.http.conf;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.server.http.DefaultServlet;
import org.server.http.Servlet;
import org.task.setter.AbstractSetter;

/**
 * url映射
 * 
 * @author Admin
 * 
 */
public class URLMappingConfig extends AbstractSetter {

	// 私有化构造
	private URLMappingConfig() {
		super("conf/http-url.cnf", getInitData());
	}

	// 路径映射
	private static String[] url_map_array = new String[0];
	// servelet映射
	private static Map<String, Servlet> servlet_map = new ConcurrentHashMap<String, Servlet>();
	// 应用添加的url映射
	private static HashSet<String> app_map_url_set = new HashSet<String>();

	static {
		// 生成一次实例，加载对象
		new URLMappingConfig();
	}

	// 初始配置文件
	static String getInitData() {
		// TODO Auto-generated method stub
		StringBuilder sb = new StringBuilder();
		sb.append("#------配置修改后立即生效-------#");
		sb.append("\r\n");
		sb.append("#默认");
		sb.append("\r\n");
		sb.append("/=");
		sb.append(DefaultServlet.class.getName());
		sb.append("\r\n");
		return sb.toString();
	}

	/**
	 * 设置url映射
	 * 
	 * @param uri
	 * @param cls
	 */
	public static void appendMapping(String uri, Class<? extends Servlet> cls) {
		try {
			Servlet e = cls.newInstance();
			servlet_map.put(uri, e);
			app_map_url_set.add(uri);
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 做一次实例化，重新加载一次映射
		new URLMappingConfig();
	}

	@Override
	public void update(Collection<String> list) {
		// TODO Auto-generated method stub
		List<String> url_colls = new ArrayList<String>();
		// 遍历获取路径数组，并生成对象
		for (String str : list) {
			String array[] = str.split("=");
			if (array.length != 2) {
				continue;
			}
			// 路径
			String url = array[0].trim();
			// 类名
			String classname = array[1].trim();
			// 为路径数组赋值
			url_colls.add(url);
			// 生成对象
			try {
				Servlet servlet = (Servlet) Class.forName(classname).newInstance();
				// 写入映射
				servlet_map.put(url, servlet);
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		List<String> url_array_temp = new ArrayList<String>();
		// 填充应用中添加的映射
		Iterator<String> app_set = app_map_url_set.iterator();
		while (app_set.hasNext()) {
			String url = app_set.next();
			url_array_temp.add(url);
		}
		for (String url_str : url_colls) {
			url_array_temp.add(url_str);
		}
		// 生成url hashset，用于碰撞移除无效的映射
		HashSet<String> hash_set = new HashSet<String>(url_array_temp);
		// 重新为映射路径数组赋值
		url_map_array = url_array_temp.toArray(new String[0]);
		// 遍历应用配置
		Iterator<Entry<String, Servlet>> it = servlet_map.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, Servlet> et = it.next();
			if (!hash_set.contains(et.getKey())) {
				// url已经无效，移除映射
				servlet_map.remove(et.getKey());
			}
		}
	}

	/**
	 * 计算出可能符合当前URL特征的servlet
	 * 
	 * @param req_uri
	 * @return
	 */
	public static String getServletURI(String req_uri) {
		for (String r : url_map_array) {
			// 找到后退出，找不到递归
			if (r.equals(req_uri)) {
				return req_uri;
			}
		}
		if (req_uri.indexOf("/") != -1) {
			String s = req_uri.substring(0, req_uri.lastIndexOf("/"));
			return getServletURI(s);// 递归调用
		}
		return req_uri;
	}

	/**
	 * 返回映射的servlet实例
	 * 
	 * @param servlet_url
	 * @return
	 */
	public static Servlet getMappServlet(String servlet_url) {
		return servlet_map.get(servlet_url);
	}

	/**
	 * 返回映射数组
	 * 
	 * @return
	 */
	public static String[] getArray() {
		return url_map_array;
	}

}
